/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 *
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_ui.htm
 *
 * Zhiqim UI is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

+(function(Z)
{

var tags = ["div", "ul", "li", "ol", "dl", "dt", "dd", "menu", "dir",
            "table", "th", "tbody", "tr", "td",
            "iframe", "frameset", "frame", "noframes",
            "blockquote", "center", "pre", "sup", "sub", "strike", "fieldset", "legend",
            "p", "span", "font", "br", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "address", "i", "b", "u", "strong", "em",
            "form", "input", "select", "textarea", "button", "a", "img", "map"];

if (Z.B.msieVer <= 8)
{//IE8只支持querySelectorAll CSS2.1，在中间套一层方法，不支持的返回空数组

    if (document.querySelectorAll){
        document.querySelectorAllNoParam = document.querySelectorAll;
    }

    document.querySelectorAll = function (selector)
    {
        try
        {
            if (selector == null)
                return document.querySelectorAllNoParam();

            var elems = [];
            var list = document.querySelectorAllNoParam(selector);
            Z.each(list, function(elem)
            {
                elems.push(elem);
            });
            return elems;
        }
        catch(e)
        {
            return [];
        }
    };

    document.querySelector = function (selector)
    {
        var elements = document.querySelectorAll(selector);
        return (elements.length) ? elements[0] : null;
    };
}

/*************************************************************************/
//定义zhiqim的通用查询类
//1.格式为new Z.Query({selector:$selector});快捷方式为Z($selector)
//2.支持类型：
//    2.1)空参数，如Z(""), Z(null), Z(undefined)
//    2.2)元素参数，如Z(document),Z(element),Z(window)
//    2.3)数组参数，如Z(Z.Query),Z(Array),Z(HTMLCollection), Z(NodeList)
//    2.4)函数参数，如Z(function(){})
//    2.5)字符串参数：
//        2.5.1)Z("body")，特定指document.body
//        2.5.2)Z("<tag>")，指定HTML标签参数，如Z("<div>"),Z("<INPUT>")
//        2.5.3)Z("html")，给定一段HTML代码，如Z("<div>abc</div>")
//        2.5.4)Z("CSS3Selector")，参数为CSS的选择器，当前仅支持5种
//            2.5.4.1)Z("#id")，指定查找id
//            2.5.4.2)Z(".class")，指定查找样式名称className
//            2.5.4.3)Z("tag#id")，相当于Z("tag").find("#id")
//            2.5.4.4)Z("tag.class")，相当于Z("tag").find(".class")
//            2.5.4.5)Z(".class#id")，相当于Z(".class").find("#id")
//            2.5.4.6)Z("#id.class")，相当于Z("#id").find(".class")
/*************************************************************************/
Z.Q = Z.Query = Z.Class.newInstance();
Z.Q.fn = Z.Query.prototype =
{
    defaults:
    {
        selector: "",
        length: 0
    },

    init: function()
    {
        var i;

        if (!this.selector)
        {//无参数情况，如Z(""), Z(null), Z(undefined)
            return this;
        }

        if (this.selector.nodeType || Z.T.isWindow(this.selector))
        {//Z(DOMElement)，如果是document/element/window
            this[0] = this.selector;
            this.length = 1;
            return this;
        }

        if (Z.T.isLikeArray(this.selector))
        {//Z(Query),Z(Array),Z(HTMLCollection), Z(NodeList), Z(Arguments)等数组或类数组，转换成多个
            for (i=0;i<this.selector.length;i++)
            {
                this[i] = this.selector[i];
            }
            this.length = this.selector.length;
            return this;
        }

        if (Z.T.isFunction(this.selector))
        {//Z(function(){})
            Z.onload(this.selector);
            this[0] = this.selector;
            this.length = 1;
            return this;
        }

        if (!Z.T.isString(this.selector))
        {//Z(object)暂不支持
            return this;
        }

        /*********************************************/
        //以下表示selector为字符串参数
        //    2.5)字符串参数：
        //        2.5.1)Z("body")，特定指document.body
        //        2.5.2)Z("<tag>")，指定HTML标签参数，如Z("<div>"),Z("<INPUT>")
        //        2.5.3)Z(html)，给定一段HTML代码，如Z("<div>abc</div>")
        //        2.5.4)Z(CSS3Selector)，参数为CSS3的选择器
        /*********************************************/

        if (this.selector === "body" && document.body)
        {//Z("body")，指向document.body
            this[0] = document.body;
            this.length = 1;
            return this;
        }

        if (this.selector.charAt(0) === "<" && this.selector.charAt(this.selector.length-1) === ">" && this.selector.length >= 3)
        {//Z("<div>") & Z(html)
            if (this.selector.length <= 12)
            {
                var tag = this.selector.substring(1, this.selector.length-1);
                if (Z.AR.contains(tags, tag))
                {//Z("<div>")，要求标记长度<=10，目前最长的是blockquote
                    this[0] = document.createElement(tag);
                    this.length = 1;
                    return this;
                }
            }

            //Z(html)
            var elements = Z.H.createElement(this.selector);
            Z.eachof(this, elements, function(elem, i)
            {
                this[i] = elem;
            });
            this.length = elements.length
            return this;
        }

        /******************************************************************/
        //其他认为是CSS3选择器，调用querySelectorAll，格式如：#id,.class,div
        /******************************************************************/

        var list = document.querySelectorAll(this.selector);
        for (i=0;i<list.length;i++){
            this[i] = list[i];
        }
        this.length = list.length;
        return this;
    },

    /*********************************************************************/
    //以下为内部相关处理方法
    /*********************************************************************/
    each: function()
    {//循环处理
        var args = [this, this];
        for (var i=0;i<arguments.length;i++){
            args[i+2] = arguments[i];
        }
        return Z.eachof.apply(this, args);
    },
    size: function()
    {//返回长度
        return this.length;
    },

    /*********************************************************************/
    //以下为元素相关处理方法
    /*********************************************************************/
    find: function(selector)
    {//在当前Query中查找子元素
        if (this.length == 0 || (selector !== Z.u && !Z.T.isString(selector)))
            return Z(null);

        if (Z.T.isDocument(this[0]))
            return Z(document.querySelectorAll(selector));

        selector = selector || "*";
        var id = this[0].getAttribute("id");
        if (id !== null)
        {//存在即保存 ID 值
            var trueId = id;
            if (Z.V.isNotEmpty(id))
            {
                if (Z(document.querySelectorAll('[id="'+id+'"]')).length === 1)
                    return Z(document.querySelectorAll('[id="'+id+'"] ' + selector));
            }
        }


        //没有ID的情况，需要设置一个
        id = "_zhiqim_selector_" + Z.random(4) + "_";
        Z.EL.set(this[0], "id", id);

        try{
            return Z(document.querySelectorAll('[id="'+id+'"] ' + selector));
        }finally{
            if (trueId !== Z.u)
                Z.EL.set(this[0], "id", trueId);
            else
                Z.EL.remove(this[0], "id");
        }
    },
    parent: function()
    {//父节点
        return Z(Z.EL.parent(this[0]));
    },
    siblings: function(selector)
    {//兄弟节点中查找
        selector = selector || "*";
        var id = Z.EL.get(this[0], "id");
        if (Z.V.isNotEmpty(id)){
            return this.parent().find('> ' + selector + ':not([id="'+id+'"])');
        }

        try{
            id = "_zhiqim_siblings_" + Z.random(4) + "_";
            Z.EL.set(this[0], "id", id);
            return this.parent().find('> ' + selector + ':not([id="'+id+'"])');
        }finally{
            Z.EL.remove(this[0], "id");
        }
    },
    next: function(selector)
    {//后面兄弟节点中查找
        selector = selector || "*";
        return this.find("+ " + selector);
    },
    nextAll: function(selector)
    {//后面所有兄弟节点中查找
        selector = selector || "*";
        return this.find("~ " + selector);
    },
    prev: function(selector)
    {//前面兄弟节点中查找
        var prevs = [];
        this.each(function(elem)
        {
            var previous = elem.previousSibling;
            if (previous)
                prevs.push(previous);
        });

        return Z(prevs).find(selector);
    },
    prevAll: function(selector)
    {//前面所有兄弟节点中查找
        var prevs = [];
        this.each(function(elem)
        {
            var previous = elem.previousSibling;
            while(previous)
            {
                prevs.push(previous);
                previous = previous.previousSibling;
            }
        });

        return Z(prevs).find(selector);
    },
    children: function(selector)
    {//子节点
        selector = selector || "*";
        return this.find("> " + selector);
    },
    nth: function(elem, selector)
    {//第n个，从1开始
        var index = -1;
        this.find(selector).each(function(item, i)
        {
            if (item != elem)
                return;

            //找到
            index = i;
            return true;
        });
        return (index == -1)?-1:(index+1);
    },

    /*****************************************************************************/
    //以下为文档操作
    /*****************************************************************************/
    appendToPos: function($selector)
    {
        if (!($selector instanceof Z.Query))
            $selector = Z($selector);

        if ($selector.css("position") === "static")
            $selector.css("position", "relative");

        return this.appendTo($selector);
    },
    remove: function()
    {
        for (var i=0;i<this.length;i++)
        {
            Z.EL.remove(this[i]);
        }

        return this;
    },

    /*********************************************************************/
    //以下为属性操作方法
    /*********************************************************************/
    val: function(values)
    {//设置可选/undefinde/String/Function类型，后续支持Array
        if (values === Z.u)
        {//没有参数表示读取第一个的值
            return (this.length > 0)?Z.EL.get(this[0], "value"):null;
        }

        //有参数表示设置每个的值
        if (Z.T.isFunction(values))
        {//回调得到String，其中this=elem,args=[elem, i]
            this.each(function(elem, i)
            {
                var value = values.call(elem, elem, i);
                if (Z.T.isString(value))
                    Z.EL.set(elem, "value", value);
            });
        }
        else
        {//不是函数的，认为是值，直接设置
            this.each(function(elem){Z.EL.set(elem, "value", values);});
        }

        return this;
    },
    attr: function(param, param2)
    {
        if (arguments.length == 1)
        {
            if (Z.T.isString(param))
            {//字符串形式表示获取第一个元素的属性，如Z(selector).attr("option");
                return Z.EL.get(this[0], param);
            }

            for (var name in param)
            {//对象形式表示设置多个属性，如Z(selector).attr({option:'none', padding: 3});
                var value = param[name];
                this.each(function(elem){Z.EL.set(elem, name, value);});
            }
        }
        else if (arguments.length == 2)
        {//字符串形式设置单个css，如Z(selector).attr("option", "0");
            this.each(function(elem){Z.EL.set(elem, param, param2);});
        }

        //其他不处理返回自己
        return this;
    },
    removeAttr: function(name)
    {
        this.each(function(elem){Z.EL.remove(elem, name);});
        return this;
    },
    className: function(className)
    {//查看
        if (this.length == 0)
            return this;

        if (className === Z.u)
            return Z.EL.className(this[0]);

        Z.EL.className(this[0], className);
        return this;
    },
    addClass: function(className)
    {//增加
        this.each(function(elem)
        {
            var classNameArr = Z.AR.toArray(className, Z.R.SPACE);
            for (var i = 0;i < classNameArr.length;i++)
            {
                Z.EL.addClass(elem, classNameArr[i]);
            }
        });
        return this;
    },
    removeClass: function(className)
    {//删除
        this.each(function(elem)
        {
            var classNameArr = Z.AR.toArray(className, Z.R.SPACE);
            for (var i = 0;i < classNameArr.length;i++)
            {
                Z.EL.removeClass(elem, classNameArr[i]);
            }
        });
        return this;
    },
    hasClass: function(className)
    {//判断
        return (this.length > 0)?Z.EL.hasClass(this[0], className):false;
    },
    toggleClass: function(className)
    {//反转
        return this.hasClass(className)?this.removeClass(className):this.addClass(className);
    },

    /************************************************************************/
    //样式部分 style & css & cssNum &opacity & display
    /************************************************************************/

    style: function(style)
    {
        if (style === Z.u)
            return Z.EL.style(this[0]);

        this.each(function(elem){Z.EL.style(elem, style);});
        return this;
    },
    css: function(param, param2)
    {
        if (!param)
        {//第一个参数没有表示无效，返回当前对象
            return this;
        }

        if (param2 === Z.u)
        {//取值，或设置多个值
            if (Z.T.isString(param))
            {//字符串形式表示获取第一个元素的css，如Z(selector).css("display");
                return Z.EL.css(this[0], param);
            }

            this.each(function(elem)
            {//对象属性方式，如Z(selector).css({left:0, top:0});
                Z.each(param, function(value, key){Z.EL.css(elem, key, value);});
            });
        }
        else
        {//设置单个值,字符串形式设置单个css，如Z(selector).css("display", "none");
            this.each(function(elem){Z.EL.css(elem, param, param2);});
        }

        //其他不处理返回自己
        return this;
    },
    cssNum: function(name)
    {
        return Z.EL.cssNum(this[0], name)
    },
    cssMaybe: function(name, value)
    {//写入时为Nil的过滤掉
        if (Z.T.isNil(value))
            return this;

        this.css(name, value);
        return this;
    },
    opacity: function(param)
    {
        return this.css("opacity", param);
    },
    display: function(param)
    {
        return this.css("display", param);
    },
    inline: function()
    {
        return this.display("inline");
    },
    block: function()
    {
        return this.display("block");
    },
    inBlock: function()
    {
        return this.display("inline-block");
    },

    /*********************************************************************/
    //保存层隐藏 & 显示
    /*********************************************************************/

    isHidden: function()
    {
        return "hidden" === this.css("visibility");
    },
    hidden: function()
    {
        return this.css("visibility", "hidden");
    },
    visible: function()
    {
        return this.css("visibility", "visible")
    },

    /*********************************************************************/
    //隐藏&显示
    /*********************************************************************/

    isHide: function()
    {
        return "none" === this.display();
    },
    hide: function()
    {
       this.each(function(elem)
       {
            var display = Z.EL.css(elem, "display");
            if (display != null && display !== "none")
            {//如果不是none则保留到临时属性display中
                Z.EL.set(elem, "data-zhiqim-display", display);
            }
            Z.EL.css(elem, "display", "none");
       });
       return this;
    },
    show: function()
    {//显示,先查是否有隐藏时的缓存，如果没有查elem缺省值
       this.each(function(elem)
       {
            var display = Z.EL.get(elem, "data-zhiqim-display");
            if (display == null || display === "none")
                display = Z.H.displayDefault(elem.nodeName);

            Z.EL.css(elem, "display", display);
       });
       return this;
    },
    toggle: function()
    {
        return this.isHide()?this.show():this.hide();
    },

    /*********************************************************************/
    //内容 text & html
    /*********************************************************************/
    text: function(text)
    {
        if (this.length > 0)
        {
            if (text === Z.u)
                return Z.EL.text(this[0]);
            else
                Z.EL.text(this[0], text);
        }

        //其他不处理返回自己
        return this;
    },
    html: function(html)
    {//仅第一个元素设置html
        if (this.length > 0)
        {
            if (html === Z.u)
                return Z.EL.html(this[0]);
            else
                Z.EL.html(this[0], html);
        }

        //其他不处理返回自己
        return this;
    },
    htmls: function(html)
    {//设置outerHTML
        if (this.length > 0)
        {
            if (html === Z.u)
                return Z.EL.htmls(this[0]);
            else
                Z.EL.htmls(this[0], html);
        }

        //其他不处理返回自己
        return this;
    },
    htmlc: function(html)
    {//仅第一个元素设置html
        if (this.length > 0)
        {
            if (html === Z.u)
                return Z.EL.htmlc(this[0]);
            else
                Z.EL.htmlc(this[0], html);
        }

        //其他不处理返回自己
        return this;
    },
    htmlx: function()
    {//获取HTML的扩展方式，对一些标记作简单处理
        if (this.length == 0)
            return null;
        var html = Z.EL.html(this[0]);
        html = Z.S.replaceAll(html, "readonly=\"\"", "readonly");
        html = Z.S.replaceAll(html, "disabled=\"\"", "disabled");
        html = Z.S.replaceAll(html, "checked=\"\"", "checked");
        html = Z.S.replaceAll(html, "selected=\"\"", "selected");
        html = Z.S.replaceAll(html, "single=\"\"", "single");
        html = Z.S.replaceAll(html, "multiple=\"\"", "multiple");
        if (html.indexOf("<thead>") == -1)
        {//没有表头部定义
            html = Z.S.replaceAll(html, "<tbody>", "");
            html = Z.S.replaceAll(html, "</tbody>", "");
        }
        return html;
    },
    htmlt: function()
    {//获取HTML的扩展方式，对一些标记作简单处理
        if (this.length == 0)
            return null;
        var html = this.htmlx();
        html = Z.S.replaceAll(html, "<", "&lt;");
        html = Z.S.replaceAll(html, ">", "&gt;");
        return html;
    },

    /*********************************************************************/
    //焦点选择 focusEnd & select
    /*********************************************************************/

    focusEnd: function()
    {//焦点移到最后
        if (this.length > 0 && this[0].nodeType){
            Z.EL.focusEnd(this[0]);
        }
        return this;
    },
    select: function()
    {//选中文本
        if (this.length > 0 && this[0].nodeType){
            this[0].select();
        }
        return this;
    },
    selection: function()
    {//选中的文本内容
        return (this.length > 0)?Z.EL.selection(this[0]):"";
    },
    isSelection: function()
    {//是否选中内容
        return Z.V.isNotEmpty(this.selection());
    },

    /*********************************************************************/
    //以下为坐标和宽高操作方法
    /*********************************************************************/
    offsetParent: function()
    {
        if (this.length == 0 || !this[0].nodeType)
            return null;

        return Z(this[0].offsetParent);
    },
    offsetWidth: function()
    {//元素本身宽度border+padding+width = style.width,不同的点:
        //1.style.width可设置百分比并返回百分比,而offsetWidth返回百分比计算的数值
        //2.style.width未设置返回空字符串,而offsetWidth一直返回计算的数值
        //3.style.width带px后缀
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        if (Z.T.isDocument(this[0]))
            return Z.D.offsetWidth(this[0]);
        else
            return this[0].offsetWidth;
    },
    offsetHeight: function()
    {//元素本身高度border+padding+height = style.height
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        if (Z.T.isDocument(this[0]))
            return Z.D.offsetHeight(this[0]);
        else
            return this[0].offsetHeight;
    },
    offsetLeft: function()
    {//元素和父元素相对左距 = style.left，火狐需除去左边框
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        return Z.EL.offsetLeft(this[0]);
    },
    offsetTop: function()
    {//元素和父元素相对上距 = style.top
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        return Z.EL.offsetTop(this[0]);
    },
    offsetLeftBody: function()
    {//元素和和绝对定位父元素相对左距 = style.left
        if (this.length == 0 || !this[0].nodeType || this[0].nodeType === 9)
            return 0;

        return Z.EL.offsetLeftBody(this[0]);
    },
    offsetTopBody: function()
    {//元素绝对定位body的上距
        if (this.length == 0 || !this[0].nodeType || this[0].nodeType === 9)
            return 0;

        return Z.EL.offsetTopBody(this[0]);
    },

    //以下为client
    clientWidth: function()
    {//元素可操作宽度padding+width
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        if (Z.T.isDocument(this[0]))
            return Z.D.clientWidth(this[0]);
        else
            return this[0].clientWidth;
    },
    clientHeight: function()
    {//元素可操作高度padding+height
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        if (Z.T.isDocument(this[0]))
            return Z.D.clientHeight(this[0]);
        else
            return this[0].clientHeight;
    },
    clientLeft: function()
    {//元素左边框 = style.borderLeftWidth
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        return this[0].clientLeft;
    },
    clientTop: function()
    {//元素上边框 = style.borderTopWidth
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        return this[0].clientHeight;
    },

    //以下为scroll
    scrollWidth: function()
    {//元素可操作宽度padding+width
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        if (Z.T.isDocument(this[0]))
            return Z.D.scrollWidth(this[0]);
        else
            return this[0].scrollWidth;
    },
    scrollHeight: function()
    {//元素可操作高度padding+height
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        if (Z.T.isDocument(this[0]))
            return Z.D.scrollHeight(this[0]);
        else
            return this[0].scrollHeight;
    },
    scrollLeft: function()
    {//元素左边框 = style.borderLeftWidth
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        if (Z.T.isDocument(this[0]))
            return Z.D.scrollLeft(this[0]);
        else
            return this[0].scrollLeft;
    },
    scrollTop: function()
    {//元素上边框 = style.borderTopWidth
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        if (Z.T.isDocument(this[0]))
            return Z.D.scrollTop(this[0]);
        else
            return this[0].scrollTop;
    },

    clientX: function()
    {//元素在绝对定位元素或浏览器窗口中的X坐标
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        //减去滚动条的值才是当前的坐标
        return this.offsetLeftBody() -(Z.body().scrollLeft+document.documentElement.scrollLeft);
    },
    clientY: function()
    {//元素在绝对定位元素或浏览器窗口中的Y坐标
        if (this.length == 0 || !this[0].nodeType)
            return 0;

        //减去滚动条的值才是当前的坐标
        return this.offsetTopBody() -(Z.body().scrollTop+document.documentElement.scrollTop);
    },
    scrollIntoView: function(bTop, offset)
    {//滚动到元素所在位置
        if (this.length == 0 || !this[0].nodeType)
            return this;

        this[0].scrollIntoView(bTop);
        if (offset){
            window.scrollTo(Z.D.scrollLeft(), Z.D.scrollTop()+offset);
        }
    },

    /*********************************************************************/
    //以下为动画方法
    /*********************************************************************/
    animate: function(cssProperties, duration, complete)
    {//1.3进行改造，暂时和fadeTo功能相同
        if (this.length == 0 || !this[0].nodeType)
            return this;

        if (!cssProperties || !Z.T.isPlainObject(cssProperties))
            return this;//当前仅支持透明作法

        duration = (!Z.T.isNumber(duration) || duration < 13)?200:duration;
        var times = Math.ceil(duration/13);

        //取第一个计算每步骤操作值
        var props = [], begins = [], ends = [], pres = [], ind=0;
        for (var prop in cssProperties)
        {
            var i = ind++;
            props[i] = prop;
            if (prop in this[0]) {
                begins[i] = Z.S.prefixNum(this[0][prop]);
            } else {
                begins[i] = Z.EL.cssNum(this[0], prop);
            }
            ends[i] = +Z.S.prefixNum(cssProperties[prop]);
            pres[i] = (ends[i] - begins[i]) / times;
        }

        //从当前慢慢到最后
        Z.timer(13, times, this,
            function(){for(var p=0;p<props.length;p++)
            {
                if (props[p] in this[0]) {
                    this[0][props[p]] = Z.S.prefixNum(this[0][props[p]]) + pres[p];
                } else {
                    this.css(props[p], this.cssNum(props[p]) + pres[p]);
                }
            }},
            function(){for(var p=0;p<props.length;p++)
            {
                if (props[p] in this[0]) {
                    this[0][props[p]] = ends[p];
                } else {
                    this.css(props[p], ends[p]);
                }
                if (Z.T.isFunction(complete)){complete.apply(this[0]);}
            }}
        );

        return this;
    },
    fadeTo: function(duration, opacity, complete)
    {//淡入到指定的透明度
        duration = (!Z.T.isNumber(duration) || duration < 13)?200:duration;
        opacity = opacity || 1;
        var times = Math.ceil(duration/13);

        var index = 0;
        var preOpacity = opacity / times;
        this.opacity(0).show();
        Z.timer(13, times, this,
            function(){this.opacity(preOpacity * index++)},
            function(){this.opacity(opacity);if (Z.T.isFunction(complete)){complete.apply(this[0]);}}
        );
    },
    fadeToggle: function(duration, complete)
    {//淡入淡出切换
        if (this.isHide() || this.opacity() == 0)
            this.fadeIn(duration, complete);
        else
            this.fadeOut(duration, complete);
    },
    fadeIn: function(duration, complete)
    {//淡入到显示
        this.fadeTo(duration, 1, complete);
    },
    fadeOut: function(duration, complete)
    {//淡出到隐藏
        duration = (!Z.T.isNumber(duration) || duration < 13)?200:duration;
        var opacity = Z.EL.opacity(this[0]) || 1;
        var times = Math.ceil(duration/13);

        var index = 0;
        var preOpacity = opacity / times;
        Z.timer(13, times, this,
            function(){this.opacity(opacity - preOpacity * index++)},
            function(){this.hide();this.opacity(1);if (Z.T.isFunction(complete)){complete.apply(this[0]);}}
        );
    },
    slideToggle: function(duration, complete)
    {//切换滑动
        if (this.length == 0 || !this[0].nodeType)
        {
            if (Z.T.isFunction(complete))
                complete();

            return this;
        }

        this.each(function(elem)
        {
            var self = Z(elem);
            if (self.isHide())
                self.slideDown(duration, complete);
            else
                self.slideUp(duration, complete);
        });

        return this;
    },
    slideDown: function(duration, complete)
    {//下滑
        if (this.length == 0 || !this[0].nodeType)
        {
            if (Z.T.isFunction(complete))
                complete();

            return this;
        }

        //计算每步骤操作值
        duration = (!Z.T.isNumber(duration) || duration < 13)?200:duration;
        var times = Math.ceil(duration/13);

        var eachNum = 0;
        this.each(function(elem)
        {
            eachNum++;
            var self = Z(elem).show().css("overflow", "hidden");
            var begHeight = 0;
            var endHeight = self.offsetHeight();
            var preHegiht = (endHeight - begHeight) / times;

            //从初始高度慢慢到最终高度
            self.css("height", begHeight);
            Z.timer(13, times, self,
                function(){self.css("height", self.offsetHeight() + preHegiht);},
                function(){self.css("height", endHeight);if (complete){complete.apply(elem);}}
            );
        });

        return this;
    },
    slideUp: function(duration, complete)
    {//上滑
        if (this.length == 0 || !this[0].nodeType)
        {
            if (Z.T.isFunction(complete))
                complete();

            return this;
        }

        //计算每步骤操作值
        duration = (!Z.T.isNumber(duration) || duration < 13)?200:duration;
        var times = Math.ceil(duration/13);

        var eachNum = 0;
        this.each(function(elem)
        {
            var self = Z(elem);
            if (self.isHide())
                return;

            eachNum++;
            self.css("overflow", "hidden");
            var begHeight = self.offsetHeight();
            var endHeight = 0;
            var preHegiht = (begHeight - endHeight) / times;

            //从初始高度慢慢到最终高度
            Z.timer(13, times, self,
                function(){self.css("height", self.offsetHeight() - preHegiht);},
                function(){self.css("height", begHeight).hide();if (complete){complete.apply(elem);}}
            );
        });

        if (complete && eachNum == 0){
            complete();
        }

        return this;
    },
    drag: function(param, callback, $this)
    {
        if (this.length == 0 || !this[0].nodeType)
            return this;

        if (param && param instanceof Z.Query)
        {//如果传入的是Query则取第一个元素
            param = param[0];
        }

        Z.drag(this[0], param, callback, $this);
        return this;
    },
    dragInParent: function(drag, parent, callback, $this)
    {
        if (this.length == 0 || !this[0].nodeType)
            return this;

        if (drag && drag instanceof Z.Query)
        {//如果传入的是Query则取第一个元素
            drag = drag[0];
        }

        if (parent && parent instanceof Z.Query)
        {//如果传入的是Query则取第一个元素
            parent = parent[0];
        }

        Z.dragInParent(this[0], drag, parent, callback, $this);
        return this;
    },

    /*********************************************************************/
    //以下为事件方法
    /*********************************************************************/
    on: function($event, $function, $this)
    {//增加事件
        var events = Z.AR.toArray($event, " ");
        for (var i=0;i<this.length;i++)
        {
            for (var j=0;j<events.length;j++)
                Z.E.add(this[i], events[j], $function, $this);
        }
        return this;
    },
    off: function($event, $function, $this)
    {//删除事件
        var events = Z.AR.toArray($event, " ");
        for (var i=0;i<this.length;i++)
        {
            for (var j=0;j<events.length;j++)
                Z.E.remove(this[i], events[j], $function, $this);
        }
        return this;
    },
    hover: function($function1, $function2, $this)
    {//鼠标进入和离开事件
        this.on("mouseenter", $function1, $this);
        this.on("mouseleave", $function2, $this);
        return this;
    },
    offhover: function($function1, $function2, $this)
    {//删除鼠标进入和离开事件
        this.off("mouseenter", $function1, $this);
        this.off("mouseleave", $function2, $this);
        return this;
    },
    mousewheel: function($function, $this)
    {//鼠标滚轮事件
        return this.on(Z.B.firefox?"DOMMouseScroll":"mousewheel", $function, $this);
    },
    offmousewheel: function($function, $this)
    {//删除鼠标滚轮事件
        return this.off(Z.B.firefox?"DOMMouseScroll":"mousewheel", $function, $this);
    }
};

/*****************************************************************************************/
//插入文档四个方法，插入到子最后，子最前，当前前面，当前后面
/*****************************************************************************************/
var inserts = ["append", "prepend", "before", "after"];
Z.each(inserts, function(item)
{
    Z.Q.fn[item] = function($selector)
    {
        if (!($selector instanceof Z.Query))
            $selector = Z($selector);

        if (this.length > 0 && $selector.length > 0 && this[0].nodeType)
        {
            var $elem = (this[0].nodeType === 9)?Z("body"):this;
            Z.EL[item].call(null, $elem[0], $selector[0]);
        }

        return this;
    }
});

var insertTos = ["appendTo", "prependTo", "insertBefore", "insertAfter"];
Z.each(insertTos, function(item, i)
{
    Z.Q.fn[item] = function($selector)
    {
        if (!($selector instanceof Z.Query))
            $selector = Z($selector);

        if (this.length > 0 && $selector.length > 0 && $selector[0].nodeType)
        {
            var $elem = ($selector[0].nodeType === 9)?Z("body"):$selector;
            Z.EL[inserts[i]].call(null, $elem[0], this[0]);
        }

        return this;
    }
});

/*****************************************************************************************/
//事件相同方法
/*****************************************************************************************/
var events = ["keydown", "keypress", "keyup", "click", "dblclick", "change", "blur", "focusin", "focusout", "focus", "input",
              "mouseenter", "mouseleave", "mouseover", "mouseout", "mouseup", "mousedown", "mousemove",
              "resize", "scroll", "load", "unload", "beforeunload"];
Z.each(events, function(event)
{
    Z.Q.fn[event] = function($function, $this)
    {
        if (arguments.length > 0)
            return this.on(event, $function, $this);

        //没参数表示触发
        this.each(function(elem){if (elem[event]) elem[event]();});
        return this;
    };
    Z.Q.fn["off"+event] = function($function, $this){return this.off(event, $function, $this);};
});

//END
})(zhiqim);
